package com.gitee.wsl.flow.coroutines

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.*


fun <T> Flow<T>.launchAndCollect(
    owner: Lifecycle,
    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
    collector:FlowCollector<T>
) = owner.coroutineScope.launch {
    flowWithLifecycle(owner,minActiveState).collect(collector)
}


inline fun <T> Flow<T>.launchAndCollectIn(
    owner: LifecycleOwner,
    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
    crossinline action: suspend CoroutineScope.(T) -> Unit
) = owner.lifecycleScope.launch {
    owner.repeatOnLifecycle(minActiveState) {
        collect {
            action(it)
        }
    }
}

fun <T> Flow<T>.collect(scope: CoroutineScope, action: suspend (value: T) -> Unit) {
    scope.launch {
        collect(action)
    }
}

fun <T> Flow<T>.collectLatest(scope: CoroutineScope, action: suspend (value: T) -> Unit) {
    scope.launch {
        collectLatest(action)
    }
}


/**
 * Runs a flow in a given coroutine scope. If the scope is cancelled, the flow will complete.
 */
fun <T> Flow<T>.flowIn(scope: CoroutineScope): Flow<T> {
    return channelFlow {
        val job = this@flowIn
            .onEach { trySend(it) }
            .onCompletion { close() }
            .launchIn(scope)

        awaitClose { job.cancel() }
    }
}
